其他
程序员应如何理解高并发中的协程
普通的函数
def func():
print("a")
print("b")
print("c")
这是一个简单的普通函数,当我们调用这个函数时会发生什么?调用func func开始执行,直到return func执行完成,返回函数A
a
b
c
So easy,有没有,有没有!从普通函数到协程
void func() {
print("a")
暂停并返回
print("b")
暂停并返回
print("c")
}
普通函数下,只有当执行完print("c")这句话后函数才会返回,但是在协程下当执行完print("a")后func就会因“暂停并返回”这段代码返回到调用函数。有的同学可能会一脸懵逼,这有什么神奇的吗?我写一个return也能返回,就像这样:void func() {
print("a")
return
print("b")
暂停并返回
print("c")
}
直接写一个return语句确实也能返回,但这样写的话return后面的代码都不会被执行到了。协程之所以神奇就神奇在当我们从协程返回后还能继续调用该协程,并且是从该协程的上一个返回点后继续执行。这足够神奇吧,就好比孙悟空说一声“定”,函数就被暂停了:void func() {
print("a")
定
print("b")
定
print("c")
}
这时我们就可以返回到调用函数,当调用函数什么时候想起该协程后可以再次调用该协程,该协程会从上一个返回点继续执行。Amazing,有没有,集中注意力,千万不要翻车。Show Me The Code
void func() {
print("a")
yield
print("b")
yield
print("c")
}
注意,这时我们的func就不再是简简单单的函数了,而是升级成为了协程,那么我们该怎么使用呢,很简单:def A():
co = func() # 得到该协程
next(co) # 调用协程
print("in function A") # do something
next(co) # 再次调用该协程
我们看到虽然func函数没有return语句,也就是说虽然没有返回任何值,但是我们依然可以写co = func()这样的代码,意思是说co就是我们拿到的协程了。接下来我们调用该协程,使用next(co),运行函数A看看执行到第3行的结果是什么:a
显然,和我们的预期一样,协程func在print("a")后因执行yield而暂停并返回函数A。接下来是第4行,这个毫无疑问,A函数在做一些自己的事情,因此会打印:a
in function A
接下来是重点的一行,当执行第5行再次调用协程时该打印什么呢?如果func是普通函数,那么会执行func的第一行代码,也就是打印a。但func不是普通函数,而是协程,我们之前说过,协程会在上一个返回点继续运行,因此这里应该执行的是func函数第一个yield之后的代码,也就是print("b")。a
in function A
b
看到了吧,协程是一个很神奇的函数,它会自己记住之前的执行状态,当再次调用时会从上一次的返回点继续执行。图形化解释
函数只是协程的一种特例
协程的历史
协程是如何实现的
一个普通线程
两个协程
总结
长按识别二维码关注
码农的荒岛求生往期精选
看完这篇还不懂线程与线程池你来打我读取文件时,程序经历了什么?终于明白了,一文彻底理解I/O多路复用从小白到高手,你需要理解同步与异步程序员应如何彻底理解回调函数高性能高并发服务器是如何实现的函数运行时在内存中是什么样子的扫码关注
码农的荒岛求生